home *** CD-ROM | disk | FTP | other *** search
/ Workbench Add-On / Workbench Add-On - Volume 1.iso / BBS-Archive / Comm / term-source.lha / Extras / Source / term-Source.lha / termPacket.c < prev    next >
C/C++ Source or Header  |  1995-06-17  |  28KB  |  1,232 lines

  1. /*
  2. **    termPacket.c
  3. **
  4. **    Support routines for the `packet window'
  5. **
  6. **    Copyright © 1990-1995 by Olaf `Olsen' Barthel
  7. **        All Rights Reserved
  8. */
  9.  
  10. #include "termGlobal.h"
  11.  
  12.     /* A custom message structure. */
  13.  
  14. struct PacketMessage
  15. {
  16.     struct Message     VanillaMessage;
  17.     LONG         Line;
  18. };
  19.  
  20.     /* Some private data required to handle both the window,
  21.      * the editing functions and the command history buffer.
  22.      */
  23.  
  24. STATIC struct Hook         PacketHook;
  25. STATIC STRPTR             PacketContents;
  26.  
  27. STATIC struct Process        *PacketProcess;
  28. STATIC struct SignalSemaphore     PacketSemaphore;
  29. STATIC struct MsgPort        *PacketPort;
  30.  
  31. STATIC LONG             PacketLine;
  32. STATIC LONG             PacketCount;
  33. STATIC STRPTR             PacketString    = NULL;
  34. STATIC LONG             PacketX    = -1,
  35.                  PacketY    = -1,
  36.                  PacketWidth    = -1,
  37.                  PacketHeight    = -1;
  38.  
  39. STATIC BYTE             HasList    = FALSE,
  40.                  Echo        = -1;
  41.                  PacketSignal    = -1;
  42.  
  43.     /* Gadget IDs */
  44.  
  45. enum    {    GAD_STRING, GAD_LIST };
  46.  
  47.     /* The menu to attach to the packet window. */
  48.  
  49. enum    {    MEN_LOADHISTORY=1,MEN_SAVEHISTORY,MEN_CLEARHISTORY,MEN_OTHERWINDOW,
  50.         MEN_TOGGLE_ECHO,MEN_QUITPANEL
  51.     };
  52.  
  53. STATIC struct NewMenu NewPacketMenu[] =
  54. {
  55.     { NM_TITLE, NULL,         0 , 0,        0, (APTR)0},
  56.     {  NM_ITEM, NULL,         0 , 0,        0, (APTR)MEN_LOADHISTORY},
  57.     {  NM_ITEM, NULL,         0 , 0,        0, (APTR)MEN_SAVEHISTORY},
  58.     {  NM_ITEM, NULL,         0 , 0,        0, (APTR)MEN_CLEARHISTORY},
  59.     {  NM_ITEM, NM_BARLABEL,     0 , 0,        0, (APTR)0},
  60.     {  NM_ITEM, NULL,         0 , 0,        0, (APTR)MEN_OTHERWINDOW},
  61.     {  NM_ITEM, NM_BARLABEL,     0 , 0,        0, (APTR)0},
  62.     {  NM_ITEM, NULL,         0 , TICK,    0, (APTR)MEN_TOGGLE_ECHO},
  63.     {  NM_ITEM, NM_BARLABEL,     0 , 0,        0, (APTR)0},
  64.     {  NM_ITEM, NULL,         0 , 0,        0, (APTR)MEN_QUITPANEL},
  65.     { NM_END, 0,             0 , 0,        0, (APTR)0}
  66. };
  67.  
  68. STATIC VOID __stdargs
  69. PacketDestructor(struct MsgItem *Item)
  70. {
  71.     Signal(PacketProcess,1L << PacketSignal);
  72. }
  73.  
  74. STATIC VOID __regargs
  75. PacketSerWrite(APTR Data,LONG Size)
  76. {
  77.     struct DataMsg Msg;
  78.  
  79.     InitMsgItem(&Msg,PacketDestructor);
  80.  
  81.     Msg . Type = DATAMSGTYPE_WRITE;
  82.     Msg . Data = Data;
  83.     Msg . Size = Size;
  84.  
  85.     Forbid();
  86.  
  87.     ClrSignal(1L << PacketSignal);
  88.  
  89.     PutMsgItem(SpecialQueue,(struct MsgItem *)&Msg);
  90.  
  91.     Wait(1L << PacketSignal);
  92.  
  93.     Permit();
  94. }
  95.  
  96. STATIC VOID __regargs
  97. PacketSerialCommand(STRPTR String)
  98. {
  99.     struct DataMsg Msg;
  100.  
  101.     InitMsgItem(&Msg,PacketDestructor);
  102.  
  103.     if(Echo)
  104.         Msg . Type = DATAMSGTYPE_SERIALCOMMAND;
  105.     else
  106.         Msg . Type = DATAMSGTYPE_SERIALCOMMANDNOECHO;
  107.  
  108.     Msg . Data = String;
  109.  
  110.     Forbid();
  111.  
  112.     ClrSignal(1L << PacketSignal);
  113.  
  114.     PutMsgItem(SpecialQueue,(struct MsgItem *)&Msg);
  115.  
  116.     Wait(1L << PacketSignal);
  117.  
  118.     Permit();
  119. }
  120.  
  121.     /* SendPacketMsg(LONG Line):
  122.      *
  123.      *    Tell the main process to display a certain line.
  124.      */
  125.  
  126. STATIC VOID __regargs
  127. SendPacketMsg(LONG Line)
  128. {
  129.     struct PacketMessage *Msg;
  130.  
  131.     if(Msg = (struct PacketMessage *)AllocVecPooled(sizeof(struct PacketMessage),MEMF_PUBLIC | MEMF_CLEAR))
  132.     {
  133.         Msg -> VanillaMessage . mn_Length    = sizeof(struct PacketMessage);
  134.         Msg -> Line                = Line;
  135.  
  136.         PutMsg(PacketPort,Msg);
  137.     }
  138. }
  139.  
  140.     /* CreateAllGadgets():
  141.      *
  142.      *    Create the packet string gadget.
  143.      */
  144.  
  145. STATIC struct Gadget * __regargs
  146. CreateAllGadgets(LONG Width,struct Gadget **GadgetArray,struct Gadget **GadgetList,APTR VisualInfo)
  147. {
  148.     struct Gadget        *Gadget;
  149.     struct NewGadget     NewGadget;
  150.  
  151.     ObtainSemaphore(&PacketSemaphore);
  152.  
  153.     memset(&NewGadget,0,sizeof(struct NewGadget));
  154.  
  155.     if(Gadget = CreateContext(GadgetList))
  156.     {
  157.         WORD Rest,StringHeight,ProtoHeight;
  158.  
  159.         StringHeight    = 3 + TextAttr . tta_YSize + 3;
  160.         ProtoHeight    = Window -> WScreen -> WBorTop + Window -> WScreen -> Font -> ta_YSize + 1 + 1 + StringHeight + 1 + Window -> WScreen -> WBorBottom;
  161.         Rest        = (PacketHeight - 2 - ProtoHeight - 2) / TextAttr . tta_YSize;
  162.  
  163.         NewGadget . ng_Width        = Width - 26;
  164.         NewGadget . ng_Height        = StringHeight;
  165.         NewGadget . ng_GadgetText    = NULL;
  166.         NewGadget . ng_TextAttr        = &TextAttr;
  167.         NewGadget . ng_VisualInfo    = VisualInfo;
  168.         NewGadget . ng_GadgetID        = GAD_STRING;
  169.         NewGadget . ng_Flags        = 0;
  170.         NewGadget . ng_LeftEdge        = 6;
  171.         NewGadget . ng_TopEdge        = Window -> WScreen -> WBorTop + Window -> WScreen -> Font -> ta_YSize + 2;
  172.  
  173.         GadgetArray[GAD_STRING] = Gadget = CreateGadget(STRING_KIND,Gadget,&NewGadget,
  174.             GTST_MaxChars,    1024,
  175.             GTST_EditHook,    &PacketHook,
  176.             GA_TabCycle,    FALSE,
  177.         TAG_DONE);
  178.  
  179.             /* If the window is large enough to display the
  180.              * list, create the list view gadget.
  181.              */
  182.  
  183.         if(Rest > 0)
  184.         {
  185.             NewGadget . ng_Height        = 2 + Rest * TextAttr . tta_YSize + 2 + StringHeight;
  186.             NewGadget . ng_GadgetID        = GAD_LIST;
  187.  
  188.             GadgetArray[GAD_LIST] = Gadget = CreateGadget(LISTVIEW_KIND,Gadget,&NewGadget,
  189.                 GTLV_ShowSelected,    GadgetArray[GAD_STRING],
  190.                 GTLV_Labels,        &PacketHistoryList,
  191.                 GTLV_Selected,        PacketCount,
  192.                 GTLV_Top,        PacketCount,
  193.             TAG_DONE);
  194.  
  195.             if(Gadget)
  196.                 HasList = TRUE;
  197.             else
  198.                 HasList = FALSE;
  199.         }
  200.         else
  201.             HasList = FALSE;
  202.     }
  203.  
  204.     ReleaseSemaphore(&PacketSemaphore);
  205.  
  206.     return(Gadget);
  207. }
  208.  
  209.     /* PacketKey(struct Hook *Hook,struct SGWork *Work,ULONG *Msg):
  210.      *
  211.      *    This is a string gadget editing call back routine
  212.      *    (a so-called `hook') which is to perform all the
  213.      *    line editing and command history actions supported
  214.      *    by the packet window.
  215.      */
  216.  
  217. STATIC ULONG __saveds __asm
  218. PacketKey(register __a0 struct Hook *Hook,register __a1 ULONG *Msg,register __a2 struct SGWork *Work)
  219. {
  220.         /* Someone activated the string gadget and
  221.          * hit a key.
  222.          */
  223.  
  224.     if(*Msg == SGH_KEY)
  225.     {
  226.             /* Right-Amiga-key was pressed, release the
  227.              * string gadget so user may select a menu
  228.              * item.
  229.              */
  230.  
  231.         if((Work -> IEvent -> ie_Qualifier & AMIGARIGHT) && Work -> IEvent -> ie_Code < 96)
  232.         {
  233.             if(!(Work -> IEvent -> ie_Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)) && (Work -> IEvent -> ie_Code == KEYCODE_X || Work -> IEvent -> ie_Code == KEYCODE_Q))
  234.                 return(TRUE);
  235.             else
  236.             {
  237.                 Work -> Actions = (Work -> Actions & ~(SGA_USE | SGA_BEEP)) | SGA_END | SGA_REUSE;
  238.                 Work -> Code = '\t';
  239.  
  240.                 CommandWindow = Work -> GadgetInfo -> gi_Window;
  241.                 CommandGadget = Work -> Gadget;
  242.             }
  243.         }
  244.  
  245.         if(Work -> IEvent -> ie_Code >= F01_CODE && Work -> IEvent -> ie_Code <= F10_CODE)
  246.         {
  247.             STATIC UBYTE __far OtherBuffer[2048];
  248.  
  249.             STRPTR    String;
  250.             LONG    Len,Index = Work -> IEvent -> ie_Code - F01_CODE;
  251.  
  252.             Forbid();
  253.  
  254.             if(Work -> IEvent -> ie_Qualifier & IEQUALIFIER_CONTROL)
  255.                 String = MacroKeys -> Keys[3][Index];
  256.             else
  257.             {
  258.                 if(Work -> IEvent -> ie_Qualifier & (IEQUALIFIER_LALT | IEQUALIFIER_RALT))
  259.                     String = MacroKeys -> Keys[2][Index];
  260.                 else
  261.                 {
  262.                     if(Work -> IEvent -> ie_Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))
  263.                         String = MacroKeys -> Keys[1][Index];
  264.                     else
  265.                         String = MacroKeys -> Keys[0][Index];
  266.                 }
  267.             }
  268.  
  269.             if(Len = strlen(String))
  270.             {
  271.                 if(Work -> BufferPos)
  272.                     CopyMem(Work -> PrevBuffer,OtherBuffer,Work -> BufferPos);
  273.  
  274.                 OtherBuffer[Work -> BufferPos] = 0;
  275.  
  276.                 strcat(OtherBuffer,String);
  277.  
  278.                 strcat(OtherBuffer,&Work -> PrevBuffer[Work -> BufferPos]);
  279.  
  280.                 if(strlen(OtherBuffer) > 1023)
  281.                     OtherBuffer[1023] = 0;
  282.  
  283.                 strcpy(Work -> WorkBuffer,OtherBuffer);
  284.  
  285.                 if(Work -> StringInfo -> UndoBuffer)
  286.                     strcpy(Work -> StringInfo -> UndoBuffer,Work -> PrevBuffer);
  287.  
  288.                 Work -> StringInfo -> UndoPos = Work -> BufferPos;
  289.  
  290.                 Work -> BufferPos    += Len;
  291.                 Work -> NumChars    += Len;
  292.  
  293.                 Work -> Actions = (Work -> Actions & ~SGA_BEEP) | SGA_USE | SGA_REDISPLAY;
  294.             }
  295.  
  296.             Permit();
  297.  
  298.             return(TRUE);
  299.         }
  300.  
  301.             /* The user pressed the cursor-right key to
  302.              * move the cursor to the next word in the buffer.
  303.              */
  304.  
  305.         if(Work -> IEvent -> ie_Code == CURSORRIGHT && (Work -> IEvent -> ie_Qualifier & IEQUALIFIER_CONTROL))
  306.         {
  307.             if(Work -> BufferPos != Work -> NumChars)
  308.             {
  309.                 WORD i,Position = -1;
  310.  
  311.                 for(i = Work -> BufferPos ; i < Work -> NumChars ; i++)
  312.                 {
  313.                     if(Work -> WorkBuffer[i] == ' ')
  314.                     {
  315.                         for( ; i < Work -> NumChars ; i++)
  316.                         {
  317.                             if(Work -> WorkBuffer[i] != ' ')
  318.                             {
  319.                                 Position = i;
  320.                                 break;
  321.                             }
  322.                         }
  323.  
  324.                         break;
  325.                     }
  326.                 }
  327.  
  328.                 if(Position != -1)
  329.                     Work -> BufferPos = Position;
  330.                 else
  331.                     Work -> BufferPos = Work -> NumChars;
  332.  
  333.                 Work -> EditOp = EO_MOVECURSOR;
  334.             }
  335.  
  336.             return(TRUE);
  337.         }
  338.  
  339.             /* The user pressed the cursor-right key to
  340.              * move the cursor to the previous word in the buffer.
  341.              */
  342.  
  343.         if(Work -> IEvent -> ie_Code == CURSORLEFT && (Work -> IEvent -> ie_Qualifier & IEQUALIFIER_CONTROL))
  344.         {
  345.             if(Work -> BufferPos)
  346.             {
  347.                 WORD i,Position = -1;
  348.  
  349.                 for(i = Work -> BufferPos ; i >= 0 ; i--)
  350.                 {
  351.                     if(Work -> WorkBuffer[i] != ' ')
  352.                     {
  353.                         Position = i;
  354.                         break;
  355.                     }
  356.                 }
  357.  
  358.                 if(Position == -1)
  359.                     Position = 0;
  360.  
  361.                 if(Position)
  362.                 {
  363.                     i = Position;
  364.  
  365.                     Position = -1;
  366.  
  367.                     for( ; i >= 0 ; i--)
  368.                     {
  369.                         if(Work -> WorkBuffer[i] == ' ')
  370.                         {
  371.                             Position = i + 1;
  372.                             break;
  373.                         }
  374.                     }
  375.                 }
  376.  
  377.                 if(Position != -1)
  378.                     Work -> BufferPos = Position;
  379.                 else
  380.                     Work -> BufferPos = 0;
  381.  
  382.                 Work -> EditOp = EO_MOVECURSOR;
  383.             }
  384.         }
  385.  
  386.             /* The user pressed the cursor-up key to
  387.              * scroll through the command history.
  388.              */
  389.  
  390.         if(Work -> IEvent -> ie_Code == CURSORUP)
  391.         {
  392.                 /* Shift key: jump to first command
  393.                  * history entry.
  394.                  */
  395.  
  396.             if(Work -> IEvent -> ie_Qualifier & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT))
  397.             {
  398.                 if(PacketLine)
  399.                     SendPacketMsg(0);
  400.             }
  401.             else
  402.             {
  403.                 if(PacketLine && PacketCount > 0)
  404.                     SendPacketMsg(PacketCount - 1);
  405.             }
  406.         }
  407.  
  408.             /* The user pressed the cursor-down key to
  409.              * scroll through the command history.
  410.              */
  411.  
  412.         if(Work -> IEvent -> ie_Code == CURSORDOWN)
  413.         {
  414.                 /* Shift key: jump to last command
  415.                  * history entry.
  416.                  */
  417.  
  418.             if(Work -> IEvent -> ie_Qualifier & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT))
  419.             {
  420.                 if(PacketLine > 0)
  421.                     SendPacketMsg(PacketLine);
  422.             }
  423.             else
  424.             {
  425.                 if(PacketCount < PacketLine)
  426.                     SendPacketMsg(PacketCount + 1);
  427.             }
  428.         }
  429.  
  430.         return(TRUE);
  431.     }
  432.     else
  433.     {
  434.         if(*Msg == SGH_CLICK)
  435.             return(TRUE);
  436.         else
  437.             return(FALSE);
  438.     }
  439. }
  440.  
  441.     /* HandlePacket():
  442.      *
  443.      *    Process the input coming through the packet window.
  444.      */
  445.  
  446. STATIC BOOLEAN
  447. HandlePacket(VOID)
  448. {
  449.     struct IntuiMessage    *Message;
  450.     struct PacketMessage    *PacketMsg;
  451.     ULONG             MsgClass,MsgCode;
  452.     struct Gadget        *MsgGadget;
  453.     struct FileRequester    *FileRequest;
  454.     UBYTE             DummyBuffer[MAX_FILENAME_LENGTH];
  455.     BOOLEAN             SwapWindow = FALSE;
  456.  
  457.     FOREVER
  458.     {
  459.         if(Wait(PORTMASK(PacketWindow -> UserPort) | SIG_KILL) & SIG_KILL)
  460.             return(TRUE);
  461.  
  462.         while(Message = (struct IntuiMessage *)GT_GetIMsg(PacketWindow -> UserPort))
  463.         {
  464.             MsgClass    = Message -> Class;
  465.             MsgCode        = Message -> Code;
  466.             MsgGadget    = (struct Gadget *)Message -> IAddress;
  467.  
  468.             GT_ReplyIMsg(Message);
  469.  
  470.                 /* Re-enable the string gadget if necessary. */
  471.  
  472.             if(MsgClass == IDCMP_RAWKEY)
  473.             {
  474.                 if(MsgCode == IECODE_UP_PREFIX|RAMIGA_CODE && CommandWindow == PacketWindow)
  475.                     ActivateGadget(CommandGadget,PacketWindow,NULL);
  476.  
  477.                 if(MsgCode == HELP_CODE)
  478.                     GuideDisplay(CONTEXT_PACKETWINDOW);
  479.             }
  480.  
  481.                 /* Menu help is required. */
  482.  
  483.             if(MsgClass == IDCMP_MENUHELP)
  484.                 GuideDisplay(CONTEXT_PACKET_MENU);
  485.  
  486.                 /* Handle the menu. */
  487.  
  488.             if(MsgClass == IDCMP_MENUPICK)
  489.             {
  490.                 struct MenuItem *MenuItem;
  491.  
  492.                 while(MsgCode != MENUNULL)
  493.                 {
  494.                     MenuItem = ItemAddress(PacketMenu,MsgCode);
  495.  
  496.                     switch((ULONG)GTMENUITEM_USERDATA(MenuItem))
  497.                     {
  498.                         case MEN_TOGGLE_ECHO:
  499.  
  500.                             if(MenuItem -> Flags & CHECKED)
  501.                                 Echo = TRUE;
  502.                             else
  503.                                 Echo = FALSE;
  504.  
  505.                             break;
  506.  
  507.                         case MEN_QUITPANEL:
  508.  
  509.                             MsgClass = IDCMP_CLOSEWINDOW;
  510.                             break;
  511.  
  512.                         case MEN_LOADHISTORY:
  513.  
  514.                             LT_LockWindow(PacketWindow);
  515.  
  516.                             if(FileRequest = GetFile(PacketWindow,LocaleString(MSG_PACKET_LOAD_HISTORY_TXT),"","",DummyBuffer,NULL,FALSE,FALSE,FALSE,LocaleString(MSG_GLOBAL_LOAD_TXT),FALSE))
  517.                             {
  518.                                 if(GetFileSize(DummyBuffer))
  519.                                 {
  520.                                     BPTR SomeFile;
  521.  
  522.                                     if(SomeFile = Open(DummyBuffer,MODE_OLDFILE))
  523.                                     {
  524.                                         if(PacketLine)
  525.                                         {
  526.                                             switch(MyEasyRequest(PacketWindow,LocaleString(MSG_PACKET_PACKET_WINDOW_STILL_HOLDS_LINES_TXT),LocaleString(MSG_PACKET_DISCARD_APPEND_CANCEL_TXT),PacketLine))
  527.                                             {
  528.                                                 case 1:    ClearPacketHistory();
  529.                                                     break;
  530.  
  531.                                                 case 0:    Close(SomeFile);
  532.                                                     SomeFile = NULL;
  533.                                                     break;
  534.                                             }
  535.                                         }
  536.  
  537.                                         if(SomeFile)
  538.                                         {
  539.                                             WORD Len;
  540.  
  541.                                             LineRead(NULL,NULL,NULL);
  542.  
  543.                                             while(Len = LineRead(SomeFile,DummyBuffer,255))
  544.                                             {
  545.                                                 DummyBuffer[Len - 1] = 0;
  546.  
  547.                                                 AddPacketHistory(DummyBuffer);
  548.                                             }
  549.  
  550.                                             Close(SomeFile);
  551.                                         }
  552.                                     }
  553.                                     else
  554.                                         ShowError(PacketWindow,ERR_LOAD_ERROR,IoErr(),DummyBuffer);
  555.                                 }
  556.  
  557.                                 FreeAslRequest(FileRequest);
  558.                             }
  559.  
  560.                             LT_UnlockWindow(PacketWindow);
  561.                             break;
  562.  
  563.                         case MEN_SAVEHISTORY:
  564.  
  565.                             LT_LockWindow(PacketWindow);
  566.  
  567.                             if(!PacketLine)
  568.                                 MyEasyRequest(PacketWindow,LocaleString(MSG_PACKET_NOTHING_IN_THE_BUFFER_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT));
  569.                             else
  570.                             {
  571.                                 if(FileRequest = GetFile(PacketWindow,LocaleString(MSG_PACKET_SAVE_HISTORY_TXT),"","",DummyBuffer,NULL,TRUE,FALSE,FALSE,LocaleString(MSG_GLOBAL_SAVE_TXT),FALSE))
  572.                                 {
  573.                                     BPTR SomeFile = NULL;
  574.                                     LONG Error = 0;
  575.  
  576.                                         /* If the file we are about
  577.                                          * to create already exists,
  578.                                          * ask the user whether we are
  579.                                          * to create, append or skip
  580.                                          * the file.
  581.                                          */
  582.  
  583.                                     if(GetFileSize(DummyBuffer))
  584.                                     {
  585.                                         switch(MyEasyRequest(PacketWindow,LocaleString(MSG_GLOBAL_FILE_ALREADY_EXISTS_TXT),LocaleString(MSG_GLOBAL_CREATE_APPEND_CANCEL_TXT),DummyBuffer))
  586.                                         {
  587.                                             case 1:    SomeFile = Open(DummyBuffer,MODE_NEWFILE);
  588.                                                 break;
  589.  
  590.                                             case 2:    if(SomeFile = Open(DummyBuffer,MODE_READWRITE))
  591.                                                 {
  592.                                                     if(Seek(SomeFile,0,OFFSET_END) == -1)
  593.                                                     {
  594.                                                         Close(SomeFile);
  595.  
  596.                                                         SomeFile = NULL;
  597.                                                     }
  598.                                                 }
  599.                                                 break;
  600.                                         }
  601.                                     }
  602.                                     else
  603.                                         SomeFile = Open(DummyBuffer,MODE_NEWFILE);
  604.  
  605.                                     if(!SomeFile)
  606.                                         Error = IoErr();
  607.                                     else
  608.                                     {
  609.                                         struct Node *SomeNode;
  610.  
  611.                                         ObtainSemaphore(&PacketSemaphore);
  612.  
  613.                                         SomeNode = PacketHistoryList . lh_Head;
  614.  
  615.                                         while(SomeNode -> ln_Succ)
  616.                                         {
  617.                                             SetIoErr(0);
  618.  
  619.                                             if(FPrintf(SomeFile,"%s\n",SomeNode -> ln_Name) < 1)
  620.                                             {
  621.                                                 Error = IoErr();
  622.  
  623.                                                 break;
  624.                                             }
  625.  
  626.                                             SomeNode = SomeNode -> ln_Succ;
  627.                                         }
  628.  
  629.                                         Close(SomeFile);
  630.  
  631.                                         if(GetFileSize(DummyBuffer))
  632.                                         {
  633.                                             AddProtection(DummyBuffer,FIBF_EXECUTE);
  634.  
  635.                                             if(Config -> MiscConfig -> CreateIcons)
  636.                                                 AddIcon(DummyBuffer,FILETYPE_TEXT,TRUE);
  637.                                         }
  638.                                         else
  639.                                             DeleteFile(DummyBuffer);
  640.  
  641.                                         ReleaseSemaphore(&PacketSemaphore);
  642.                                     }
  643.  
  644.                                     if(Error)
  645.                                         ShowError(PacketWindow,ERR_SAVE_ERROR,Error,DummyBuffer);
  646.  
  647.                                     FreeAslRequest(FileRequest);
  648.                                 }
  649.                             }
  650.  
  651.                             LT_UnlockWindow(PacketWindow);
  652.                             break;
  653.  
  654.                         case MEN_CLEARHISTORY:
  655.  
  656.                             LT_LockWindow(PacketWindow);
  657.  
  658.                             ClearPacketHistory();
  659.  
  660.                             LT_UnlockWindow(PacketWindow);
  661.                             break;
  662.  
  663.                         case MEN_OTHERWINDOW:
  664.  
  665.                             SwapWindow = TRUE;
  666.                             break;
  667.                     }
  668.  
  669.                     MsgCode = MenuItem -> NextSelect;
  670.                 }
  671.  
  672.                 ActivateGadget(PacketGadgetArray[GAD_STRING],PacketWindow,NULL);
  673.             }
  674.  
  675.                 /* Shut down. */
  676.  
  677.             if(MsgClass == IDCMP_CLOSEWINDOW)
  678.             {
  679.                 Forbid();
  680.  
  681.                 if(!(SetSignal(0,SIG_KILL) & SIG_KILL))
  682.                     return(FALSE);
  683.                 else
  684.                     return(TRUE);
  685.             }
  686.  
  687.                 /* Activate the string gadget as well. */
  688.  
  689.             if(MsgClass == IDCMP_ACTIVEWINDOW)
  690.                 ActivateGadget(PacketGadgetArray[GAD_STRING],PacketWindow,NULL);
  691.  
  692.             if(MsgClass == IDCMP_NEWSIZE)
  693.             {
  694.                 PacketWindow -> Flags |= WFLG_RMBTRAP;
  695.  
  696.                 strcpy(DummyBuffer,PacketContents);
  697.  
  698.                 RemoveGList(PacketWindow,PacketGadgetList,(UWORD)-1);
  699.  
  700.                 FreeGadgets(PacketGadgetList);
  701.  
  702.                 PacketGadgetList = NULL;
  703.  
  704.                 SetAPen(PacketWindow -> RPort,DrawInfo -> dri_Pens[BACKGROUNDPEN]);
  705.                 RectFill(PacketWindow -> RPort,PacketWindow -> BorderLeft,PacketWindow -> BorderTop,PacketWindow -> Width - PacketWindow -> BorderRight,PacketWindow -> Height - PacketWindow -> BorderBottom);
  706.                 RefreshWindowFrame(PacketWindow);
  707.  
  708.                 PacketHeight    = PacketWindow -> Height;
  709.                 PacketWidth    = PacketWindow -> Width;
  710.  
  711.                 ObtainSemaphore(&PacketSemaphore);
  712.  
  713.                 if(CreateAllGadgets(PacketWindow -> Width,PacketGadgetArray,&PacketGadgetList,VisualInfo))
  714.                 {
  715.                     PacketContents = ((struct StringInfo *)PacketGadgetArray[GAD_STRING] -> SpecialInfo) -> Buffer;
  716.  
  717.                     AddGList(PacketWindow,PacketGadgetList,(UWORD)-1,(UWORD)-1,NULL);
  718.                     RefreshGList(PacketGadgetList,PacketWindow,NULL,(UWORD)-1);
  719.                     GT_RefreshWindow(PacketWindow,NULL);
  720.  
  721.                     ReleaseSemaphore(&PacketSemaphore);
  722.  
  723.                     PacketWindow -> Flags &= ~WFLG_RMBTRAP;
  724.  
  725.                     GT_SetGadgetAttrs(PacketGadgetArray[GAD_STRING],PacketWindow,NULL,
  726.                         GTST_String,    DummyBuffer,
  727.                     TAG_DONE);
  728.  
  729.                     ActivateGadget(PacketGadgetArray[GAD_STRING],PacketWindow,NULL);
  730.                 }
  731.                 else
  732.                 {
  733.                     DisplayBeep(PacketWindow -> WScreen);
  734.  
  735.                     ReleaseSemaphore(&PacketSemaphore);
  736.  
  737.                     if(!(SetSignal(0,SIG_KILL) & SIG_KILL))
  738.                         return(FALSE);
  739.                     else
  740.                         return(TRUE);
  741.                 }
  742.             }
  743.  
  744.             if(MsgClass == IDCMP_MOUSEBUTTONS)
  745.                 ActivateGadget(PacketGadgetArray[GAD_STRING],PacketWindow,NULL);
  746.  
  747.                 /* User has entered a string. */
  748.  
  749.             if(MsgClass == IDCMP_GADGETUP)
  750.             {
  751.                 switch(MsgGadget -> GadgetID)
  752.                 {
  753.                     case GAD_STRING:
  754.  
  755.                         if(MsgCode != '\t')
  756.                         {
  757.                                 /* Is there anything in the buffer at all? */
  758.  
  759.                             if(PacketContents[0])
  760.                             {
  761.                                 strcpy(DummyBuffer,PacketContents);
  762.  
  763.                                 if(PacketString)
  764.                                 {
  765.                                     if(strcmp(PacketString,DummyBuffer))
  766.                                         AddPacketHistory(DummyBuffer);
  767.  
  768.                                     PacketString = NULL;
  769.                                 }
  770.                                 else
  771.                                     AddPacketHistory(DummyBuffer);
  772.  
  773.                                     /* Convert alien IBM characters. */
  774.  
  775.                                 if(Config -> TerminalConfig -> FontMode == FONT_IBM)
  776.                                 {
  777.                                     UBYTE Char;
  778.                                     WORD i;
  779.  
  780.                                     for(i = 0 ; i < strlen(DummyBuffer) ; i++)
  781.                                     {
  782.                                         if(Char = IBMConversion[DummyBuffer[i]])
  783.                                             DummyBuffer[i] = Char;
  784.                                     }
  785.                                 }
  786.  
  787.                                     /* Execute the command. */
  788.  
  789.                                 PacketSerialCommand(DummyBuffer);
  790.                             }
  791.  
  792.                                 /* Clear the packet window string
  793.                                  * gadget.
  794.                                  */
  795.  
  796.                             GT_SetGadgetAttrs(PacketGadgetArray[GAD_STRING],PacketWindow,NULL,
  797.                                 GTST_String,    "",
  798.                             TAG_DONE);
  799.  
  800.                                 /* Send a terminating `CR'. */
  801.  
  802.                             switch(Config -> TerminalConfig -> SendCR)
  803.                             {
  804.                                 case EOL_CR:
  805.  
  806.                                     PacketSerWrite("\r",1);
  807.                                     break;
  808.  
  809.                                 case EOL_LF:
  810.  
  811.                                     PacketSerWrite("\n",1);
  812.                                     break;
  813.  
  814.                                 case EOL_CRLF:
  815.  
  816.                                     PacketSerWrite("\r\n",2);
  817.                                     break;
  818.  
  819.                                 case EOL_LFCR:
  820.  
  821.                                     PacketSerWrite("\n\r",2);
  822.                                     break;
  823.                             }
  824.  
  825.                                 /* Re-activate the string gadget. */
  826.  
  827.                             ActivateGadget(PacketGadgetArray[GAD_STRING],PacketWindow,NULL);
  828.                         }
  829.  
  830.                         break;
  831.  
  832.                     case GAD_LIST:
  833.  
  834.                         ActivateGadget(PacketGadgetArray[GAD_STRING],PacketWindow,NULL);
  835.                         break;
  836.                 }
  837.             }
  838.  
  839.             if(SwapWindow)
  840.             {
  841.                 BumpWindow(Window);
  842.  
  843.                 SwapWindow = FALSE;
  844.             }
  845.         }
  846.  
  847.         if(PacketMsg = (struct PacketMessage *)GetMsg(PacketPort))
  848.         {
  849.             struct Node *Node;
  850.  
  851.             ObtainSemaphore(&PacketSemaphore);
  852.  
  853.             if(Node = GetListNode(PacketMsg -> Line,&PacketHistoryList))
  854.             {
  855.                 PacketString = Node -> ln_Name;
  856.  
  857.                 if(HasList)
  858.                 {
  859.                     GT_SetGadgetAttrs(PacketGadgetArray[GAD_LIST],PacketWindow,NULL,
  860.                         GTLV_Selected,    PacketMsg -> Line,
  861.                         GTLV_Top,    PacketMsg -> Line,
  862.                     TAG_DONE);
  863.                 }
  864.                 else
  865.                 {
  866.                     GT_SetGadgetAttrs(PacketGadgetArray[GAD_STRING],PacketWindow,NULL,
  867.                         GTST_String,    Node -> ln_Name,
  868.                     TAG_DONE);
  869.                 }
  870.             }
  871.             else
  872.             {
  873.                 PacketString = NULL;
  874.  
  875.                 GT_SetGadgetAttrs(PacketGadgetArray[GAD_STRING],PacketWindow,NULL,
  876.                     GTST_String,    "",
  877.                 TAG_DONE);
  878.             }
  879.  
  880.             ReleaseSemaphore(&PacketSemaphore);
  881.  
  882.             PacketCount = PacketMsg -> Line;
  883.  
  884.             FreeVecPooled(PacketMsg);
  885.  
  886.             ActivateGadget(PacketGadgetArray[GAD_STRING],PacketWindow,NULL);
  887.         }
  888.     }
  889. }
  890.  
  891. STATIC VOID __saveds
  892. PacketProcessEntry(VOID)
  893. {
  894.     BOOLEAN RingBack = TRUE;
  895.  
  896.     if((PacketSignal = AllocSignal(-1)) != -1)
  897.     {
  898.  
  899.         if(PacketPort = (struct MsgPort *)AllocVecPooled(sizeof(struct MsgPort),MEMF_PUBLIC | MEMF_CLEAR))
  900.         {
  901.             struct Message *Message;
  902.  
  903.             if(PacketMenu = CreateMenus(NewPacketMenu,TAG_DONE))
  904.             {
  905.                 if(LayoutMenus(PacketMenu,VisualInfo,
  906.                     GTMN_TextAttr,        &UserFont,
  907.                     GTMN_NewLookMenus,    TRUE,
  908.  
  909.                     AmigaGlyph ? GTMN_AmigaKey :  TAG_IGNORE, AmigaGlyph,
  910.                     CheckGlyph ? GTMN_Checkmark : TAG_IGNORE, CheckGlyph,
  911.                 TAG_DONE))
  912.                 {
  913.                     LONG ProtoHeight;
  914.  
  915.                     ProtoHeight = Window -> WScreen -> WBorTop + Window -> WScreen -> Font -> ta_YSize + 1 + 1 + 3 + TextAttr . tta_YSize + 3 + 1 + Window -> WScreen -> WBorBottom;
  916.  
  917.                     if(PacketWidth == -1)
  918.                         PacketWidth = Window -> Width;
  919.  
  920.                     if(PacketHeight < ProtoHeight)
  921.                         PacketHeight = ProtoHeight;
  922.  
  923.                     if(PacketX == -1 || (PacketX + PacketWidth > Window -> WScreen -> Width))
  924.                     {
  925.                         PacketX = Window -> LeftEdge;
  926.  
  927.                         if(PacketX + PacketWidth > Window -> WScreen -> Width)
  928.                             PacketWidth = Window -> WScreen -> Width - PacketX;
  929.                     }
  930.  
  931.                     if(PacketY == -1 || (PacketY + PacketHeight > Window -> WScreen -> Height))
  932.                     {
  933.                         PacketY = Window -> TopEdge + Window -> Height;
  934.  
  935.                         if(PacketY + PacketHeight > Window -> WScreen -> Height)
  936.                             PacketHeight = ProtoHeight;
  937.                     }
  938.  
  939.                     if(CreateAllGadgets(PacketWidth,PacketGadgetArray,&PacketGadgetList,VisualInfo))
  940.                     {
  941.                         if(PacketWindow = OpenWindowTags(NULL,
  942.                             WA_Width,        PacketWidth,
  943.                             WA_Height,        PacketHeight,
  944.  
  945.                             WA_Left,        PacketX,
  946.                             WA_Top,            PacketY,
  947.  
  948.                             WA_Activate,        TRUE,
  949.                             WA_DragBar,        TRUE,
  950.                             WA_DepthGadget,        TRUE,
  951.                             WA_CloseGadget,        TRUE,
  952.                             WA_RMBTrap,        TRUE,
  953.                             WA_SizeGadget,        TRUE,
  954.                             WA_MinWidth,        80,
  955.                             WA_MinHeight,        ProtoHeight,
  956.                             WA_MaxWidth,        Window -> WScreen -> Width,
  957.                             WA_MaxHeight,        Window -> WScreen -> Height,
  958.                             WA_CustomScreen,    Window -> WScreen,
  959.                             WA_NoCareRefresh,    TRUE,
  960.                             WA_NewLookMenus,    TRUE,
  961.                             WA_BackFill,        &BackfillHook,
  962.  
  963.                             WA_IDCMP,        STRINGIDCMP | LISTVIEWIDCMP | IDCMP_NEWSIZE | IDCMP_SIZEVERIFY | IDCMP_CLOSEWINDOW | IDCMP_MENUPICK | IDCMP_ACTIVEWINDOW | IDCMP_RAWKEY | IDCMP_MOUSEBUTTONS | IDCMP_MENUHELP,
  964.                             WA_MenuHelp,        TRUE,
  965.  
  966.                             WA_Title,        LocaleString(MSG_GLOBAL_PACKET_WINDOW_TXT),
  967.  
  968.                             AmigaGlyph ? WA_AmigaKey  : TAG_IGNORE, AmigaGlyph,
  969.                             CheckGlyph ? WA_Checkmark : TAG_IGNORE, CheckGlyph,
  970.                         TAG_DONE))
  971.                         {
  972.                             APTR OldPtr;
  973.  
  974.                             SetAPen(PacketWindow -> RPort,DrawInfo -> dri_Pens[BACKGROUNDPEN]);
  975.                             SetDrMd(PacketWindow -> RPort,JAM1);
  976.                             RectFill(PacketWindow -> RPort,PacketWindow -> BorderLeft,PacketWindow -> BorderTop,PacketWindow -> Width - (PacketWindow -> BorderRight + 1),PacketWindow -> Height - (PacketWindow -> BorderBottom + 1));
  977.  
  978.                             PacketPort -> mp_Flags        = PA_SIGNAL;
  979.                             PacketPort -> mp_SigBit        = PacketWindow -> UserPort -> mp_SigBit;
  980.                             PacketPort -> mp_SigTask    = PacketWindow -> UserPort -> mp_SigTask;
  981.  
  982.                             NewList(&PacketPort -> mp_MsgList);
  983.  
  984.                             PacketHook . h_Entry        = (LONG (*)())PacketKey;
  985.                             PacketHook . h_SubEntry        = NULL;
  986.                             PacketHook . h_Data        = NULL;
  987.  
  988.                             PacketContents = ((struct StringInfo *)PacketGadgetArray[GAD_STRING] -> SpecialInfo) -> Buffer;
  989.  
  990.                             AddGList(PacketWindow,PacketGadgetList,(UWORD)-1,(UWORD)-1,NULL);
  991.                             RefreshGList(PacketGadgetList,PacketWindow,NULL,(UWORD)-1);
  992.                             GT_RefreshWindow(PacketWindow,NULL);
  993.  
  994.                             SetMenuStrip(PacketWindow,PacketMenu);
  995.  
  996.                             PacketWindow -> Flags &= ~WFLG_RMBTRAP;
  997.  
  998.                             ActivateGadget(PacketGadgetArray[GAD_STRING],PacketWindow,NULL);
  999.  
  1000.                             PacketProcess = (struct Process *)FindTask(NULL);
  1001.  
  1002.                             OldPtr = PacketProcess -> pr_WindowPtr;
  1003.  
  1004.                             PacketProcess -> pr_WindowPtr = PacketWindow;
  1005.  
  1006.                             Signal(ThisProcess,SIG_HANDSHAKE);
  1007.  
  1008.                             RingBack = HandlePacket();
  1009.  
  1010.                             PacketProcess -> pr_WindowPtr = OldPtr;
  1011.  
  1012.                             PacketWindow -> Flags |= WFLG_RMBTRAP;
  1013.  
  1014.                             ClearMenuStrip(PacketWindow);
  1015.  
  1016.                             RemoveGList(PacketWindow,PacketGadgetList,(UWORD)-1);
  1017.  
  1018.                             PacketX        = PacketWindow -> LeftEdge;
  1019.                             PacketY        = PacketWindow -> TopEdge;
  1020.  
  1021.                             PacketWidth    = PacketWindow -> Width;
  1022.                             PacketHeight    = PacketWindow -> Height;
  1023.  
  1024.                             LT_DeleteWindowLock(PacketWindow);
  1025.  
  1026.                             CloseWindow(PacketWindow);
  1027.  
  1028.                             PacketWindow = NULL;
  1029.                         }
  1030.  
  1031.                         FreeGadgets(PacketGadgetList);
  1032.  
  1033.                         PacketGadgetList = NULL;
  1034.                     }
  1035.                 }
  1036.  
  1037.                 FreeMenus(PacketMenu);
  1038.  
  1039.                 PacketMenu = NULL;
  1040.             }
  1041.  
  1042.             while(Message = GetMsg(PacketPort))
  1043.                 FreeVecPooled(Message);
  1044.  
  1045.             FreeVecPooled(PacketPort);
  1046.  
  1047.             PacketPort = NULL;
  1048.         }
  1049.  
  1050.         FreeSignal(PacketSignal);
  1051.  
  1052.         PacketSignal = -1;
  1053.     }
  1054.  
  1055.     Forbid();
  1056.  
  1057.     PacketProcess = NULL;
  1058.  
  1059.     if(RingBack)
  1060.         Signal(ThisProcess,SIG_HANDSHAKE);
  1061.     else
  1062.         CheckItem(MEN_PACKET_WINDOW,FALSE);
  1063. }
  1064.  
  1065.     /* ClearPacketHistory():
  1066.      *
  1067.      *    Release the command history.
  1068.      */
  1069.  
  1070. VOID
  1071. ClearPacketHistory()
  1072. {
  1073.     if(PacketProcess)
  1074.     {
  1075.         ObtainSemaphore(&PacketSemaphore);
  1076.  
  1077.         if(HasList)
  1078.         {
  1079.             GT_SetGadgetAttrs(PacketGadgetArray[GAD_LIST],PacketWindow,NULL,
  1080.                 GTLV_Labels,~0,
  1081.             TAG_DONE);
  1082.         }
  1083.  
  1084.         FreeList(&PacketHistoryList);
  1085.  
  1086.         PacketCount = PacketLine = 0;
  1087.  
  1088.         if(HasList)
  1089.         {
  1090.             GT_SetGadgetAttrs(PacketGadgetArray[GAD_LIST],PacketWindow,NULL,
  1091.                 GTLV_Labels,&PacketHistoryList,
  1092.             TAG_DONE);
  1093.         }
  1094.  
  1095.         PacketString = NULL;
  1096.  
  1097.         ReleaseSemaphore(&PacketSemaphore);
  1098.     }
  1099. }
  1100.  
  1101.     /* AddPacketHistory(STRPTR Buffer):
  1102.      *
  1103.      *    Add a line to the packet window command history. This
  1104.      *    works very much the same as the AddLine()-routine.
  1105.      */
  1106.  
  1107. VOID __regargs
  1108. AddPacketHistory(STRPTR Buffer)
  1109. {
  1110.     if(PacketProcess)
  1111.     {
  1112.         struct Node *SomeNode;
  1113.  
  1114.         ObtainSemaphore(&PacketSemaphore);
  1115.  
  1116.         if(HasList)
  1117.         {
  1118.             GT_SetGadgetAttrs(PacketGadgetArray[GAD_LIST],PacketWindow,NULL,
  1119.                 GTLV_Labels,    ~0,
  1120.             TAG_DONE);
  1121.         }
  1122.  
  1123.         if(SomeNode = CreateNode(Buffer))
  1124.         {
  1125.             AddTail(&PacketHistoryList,SomeNode);
  1126.  
  1127.             PacketCount = ++PacketLine;
  1128.         }
  1129.  
  1130.         if(HasList)
  1131.         {
  1132.             GT_SetGadgetAttrs(PacketGadgetArray[GAD_LIST],PacketWindow,NULL,
  1133.                 GTLV_Top,    PacketCount - 1,
  1134.                 GTLV_Labels,    &PacketHistoryList,
  1135.             TAG_DONE);
  1136.         }
  1137.  
  1138.         ReleaseSemaphore(&PacketSemaphore);
  1139.     }
  1140. }
  1141.  
  1142.     /* DeletePacketWindow():
  1143.      *
  1144.      *    Delete the packet window and release the command
  1145.      *    history.
  1146.      */
  1147.  
  1148. VOID __regargs
  1149. DeletePacketWindow(BYTE WindowOnly)
  1150. {
  1151.     CheckItem(MEN_PACKET_WINDOW,FALSE);
  1152.  
  1153.     if(PacketProcess)
  1154.     {
  1155.         Forbid();
  1156.  
  1157.         ClrSignal(SIG_HANDSHAKE);
  1158.  
  1159.         Signal(PacketProcess,SIG_KILL);
  1160.  
  1161.         Wait(SIG_HANDSHAKE);
  1162.  
  1163.         Permit();
  1164.  
  1165.         if(!WindowOnly)
  1166.         {
  1167.             HasList = FALSE;
  1168.  
  1169.             FreeList(&PacketHistoryList);
  1170.  
  1171.             PacketCount = PacketLine = 0;
  1172.  
  1173.             PacketString = NULL;
  1174.         }
  1175.     }
  1176. }
  1177.  
  1178.     /* CreatePacketWindow():
  1179.      *
  1180.      *    Open the packet window and allocate the command history
  1181.      *    buffer.
  1182.      */
  1183.  
  1184. BYTE
  1185. CreatePacketWindow()
  1186. {
  1187.     if(Echo == -1)
  1188.         Echo = Config -> SerialConfig -> Duplex;
  1189.  
  1190.     if(!PacketProcess)
  1191.     {
  1192.         InitSemaphore(&PacketSemaphore);
  1193.  
  1194.         LocalizeMenu(NewPacketMenu,MSG_PACKET_PROJECT_MEN);
  1195.  
  1196.         Forbid();
  1197.  
  1198.         if(CreateNewProcTags(
  1199.             NP_Name,    "term Packet Process",
  1200.             NP_Priority,    SysBase -> ThisTask -> tc_Node . ln_Pri,
  1201.             NP_Entry,    PacketProcessEntry,
  1202.             NP_StackSize,    6000,
  1203.         TAG_DONE))
  1204.         {
  1205.             ClrSignal(SIG_HANDSHAKE);
  1206.  
  1207.             Wait(SIG_HANDSHAKE);
  1208.         }
  1209.  
  1210.         Permit();
  1211.     }
  1212.  
  1213.     if(PacketProcess)
  1214.     {
  1215.         Forbid();
  1216.  
  1217.         ActivateWindow(PacketWindow);
  1218.  
  1219.         CheckItem(MEN_PACKET_WINDOW,TRUE);
  1220.  
  1221.         Permit();
  1222.  
  1223.         return(TRUE);
  1224.     }
  1225.     else
  1226.     {
  1227.         CheckItem(MEN_PACKET_WINDOW,FALSE);
  1228.  
  1229.         return(FALSE);
  1230.     }
  1231. }
  1232.